import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import least_squares
from scipy import signal
from datetime import datetime, timedelta
import tkinter as tk
from tkinter import ttk, messagebox
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
import matplotlib
matplotlib.use('TkAgg')

# 设置中文显示
matplotlib.rcParams['font.sans-serif'] = ['SimHei']
matplotlib.rcParams['axes.unicode_minus'] = False


class CometBrightnessApp:
    def __init__(self, root):
        self.root = root
        self.root.title("彗星亮度预测工具 v1.0.2")
        self.setup_ui()

    def setup_ui(self):
        """设置用户界面"""
        # 主框架
        main_frame = ttk.Frame(self.root, padding="10")
        main_frame.pack(fill=tk.BOTH, expand=True)

        # 左侧图表区域
        left_frame = ttk.Frame(main_frame)
        left_frame.pack(side=tk.LEFT, fill=tk.BOTH, expand=True, padx=(0, 5))

        # 右侧控制区域
        right_frame = ttk.Frame(main_frame, width=450)
        right_frame.pack(side=tk.RIGHT, fill=tk.Y, padx=(5, 0))
        right_frame.pack_propagate(False)

        # 创建图表
        self.fig, (self.ax1, self.ax2) = plt.subplots(2, 1, figsize=(10, 8))
        self.canvas = FigureCanvasTkAgg(self.fig, master=left_frame)
        self.canvas.get_tk_widget().pack(fill=tk.BOTH, expand=True)

        # 创建鼠标悬停文本
        self.mouse_text = self.ax1.text(0.02, 0.95, '', transform=self.ax1.transAxes,
                                        bbox=dict(facecolor='white', alpha=0.8))

        # 添加鼠标移动事件
        self.cid = self.canvas.mpl_connect(
            'motion_notify_event', self.on_mouse_move)

        # 右侧控制面板
        self.setup_control_panel(right_frame)

        # 初始化数据
        self.current_dates = None
        self.orbit_m_pred = None
        self.obs_m_pred = None

        # 自动填充示例数据
        self.fill_sample_data()

    def on_mouse_move(self, event):
        """鼠标移动事件处理"""
        if not event.inaxes or self.current_dates is None:
            self.mouse_text.set_text('')
            self.canvas.draw_idle()
            return

        # 获取鼠标x坐标对应的日期
        x = event.xdata
        if x is None:
            return

        # 找到最接近的日期索引
        days = [(date - self.current_dates[0]
                 ).days for date in self.current_dates]
        idx = np.argmin(np.abs(np.array(days) - x))

        # 显示当前点的信息
        date_str = self.current_dates[idx].strftime('%Y-%m-%d')
        orbit_mag = f"{self.orbit_m_pred[idx]:.2f}" if self.orbit_m_pred is not None else "N/A"
        obs_mag = f"{self.obs_m_pred[idx]:.2f}" if self.obs_m_pred is not None else "N/A"

        text = f"日期: {date_str}\n轨道计算: {orbit_mag}等\n观测拟合: {obs_mag}等"
        self.mouse_text.set_text(text)

        # 更新图表
        self.canvas.draw_idle()

    def setup_control_panel(self, parent):
        """设置右侧控制面板"""
        # 创建笔记本式选项卡
        notebook = ttk.Notebook(parent)
        notebook.pack(fill=tk.BOTH, expand=True)

        # 第一个标签页 - 轨道参数
        orbit_tab = ttk.Frame(notebook)
        notebook.add(orbit_tab, text="轨道参数")
        self.setup_orbit_tab(orbit_tab)

        # 第二个标签页 - 星等预测
        mag_tab = ttk.Frame(notebook)
        notebook.add(mag_tab, text="星等预测")
        self.setup_mag_tab(mag_tab)

        # 第三个标签页 - 日期查询
        query_tab = ttk.Frame(notebook)
        notebook.add(query_tab, text="日期查询")
        self.setup_query_tab(query_tab)

    def setup_orbit_tab(self, parent):
        """设置轨道参数标签页"""
        # 彗星选择
        comet_frame = ttk.LabelFrame(parent, text="彗星选择", padding="10")
        comet_frame.pack(fill=tk.X, pady=5)

        ttk.Label(comet_frame, text="选择彗星:").grid(
            row=0, column=0, padx=5, pady=2, sticky=tk.W)
        self.comet_var = tk.StringVar()
        comet_combo = ttk.Combobox(
            comet_frame, textvariable=self.comet_var, width=25)
        comet_combo['values'] = (
            "C/2025 A6 (Lemmon)",
            "C/2025 R2 (SWAN)",
            "C/2025 K1 (ATLAS)",
            "210P/Christensen",
            "3I/ATLAS",
            "C/2024 E1 (Wierzchos)"
        )
        comet_combo.grid(row=0, column=1, padx=5, pady=2)
        comet_combo.bind('<<ComboboxSelected>>', self.on_comet_selected)

        # 彗星信息
        info_frame = ttk.LabelFrame(parent, text="彗星信息", padding="10")
        info_frame.pack(fill=tk.X, pady=5)

        ttk.Label(info_frame, text="彗星名称:").grid(
            row=0, column=0, padx=5, pady=2, sticky=tk.W)
        self.name_entry = ttk.Entry(info_frame, width=25)
        self.name_entry.grid(row=0, column=1, padx=5, pady=2)

        # 轨道参数
        orbit_frame = ttk.LabelFrame(
            parent, text="轨道元素 (来源: MPC星历表服务)", padding="10")
        orbit_frame.pack(fill=tk.X, pady=5)

        orbit_params = [
            ("q (近日点距离 AU)", "perihelion_distance"),
            ("a (半长轴 AU)", "semi_major_axis"),
            ("e (偏心率)", "eccentricity"),
            ("ω (近日点幅角 °)", "arg_perihelion"),
            ("Ω (升交点赤经 °)", "long_asc_node"),
            ("i (轨道倾角 °)", "inclination"),
            ("P (轨道周期 年)", "orbital_period"),
            ("T (近日点时间)", "perihelion_time"),
            ("历元时间", "epoch_time")
        ]

        self.orbit_entries = {}
        for i, (label, key) in enumerate(orbit_params):
            ttk.Label(orbit_frame, text=label).grid(
                row=i, column=0, padx=5, pady=1, sticky=tk.W)
            entry = ttk.Entry(orbit_frame, width=15)
            entry.grid(row=i, column=1, padx=5, pady=1)
            self.orbit_entries[key] = entry

        # 控制按钮
        button_frame = ttk.Frame(parent)
        button_frame.pack(fill=tk.X, pady=10)

        ttk.Button(button_frame, text="重置参数", command=self.clear_entries).grid(
            row=0, column=0, padx=5)

    def setup_mag_tab(self, parent):
        """设置星等预测标签页"""
        # 星等参数 - 轨道计算
        orbit_frame = ttk.LabelFrame(
            parent, text="轨道计算预测 (MPC参数)", padding="10")
        orbit_frame.pack(fill=tk.X, pady=5)

        ttk.Label(orbit_frame, text="绝对星等 H:").grid(
            row=0, column=0, padx=5, pady=2, sticky=tk.W)
        self.orbit_H_entry = ttk.Entry(orbit_frame, width=10)
        self.orbit_H_entry.grid(row=0, column=1, padx=5, pady=2)

        ttk.Label(orbit_frame, text="斜率参数 n:").grid(
            row=1, column=0, padx=5, pady=2, sticky=tk.W)
        self.orbit_n_entry = ttk.Entry(orbit_frame, width=10)
        self.orbit_n_entry.grid(row=1, column=1, padx=5, pady=2)

        # 星等参数 - 观测拟合
        obs_frame = ttk.LabelFrame(
            parent, text="观测拟合预测 (COBS参数)", padding="10")
        obs_frame.pack(fill=tk.X, pady=5)

        ttk.Label(obs_frame, text="绝对星等 H:").grid(
            row=0, column=0, padx=5, pady=2, sticky=tk.W)
        self.obs_H_entry = ttk.Entry(obs_frame, width=10)
        self.obs_H_entry.grid(row=0, column=1, padx=5, pady=2)

        ttk.Label(obs_frame, text="斜率参数 n:").grid(
            row=1, column=0, padx=5, pady=2, sticky=tk.W)
        self.obs_n_entry = ttk.Entry(obs_frame, width=10)
        self.obs_n_entry.grid(row=1, column=1, padx=5, pady=2)

        # 预测控制
        pred_frame = ttk.LabelFrame(parent, text="预测控制", padding="10")
        pred_frame.pack(fill=tk.X, pady=5)

        ttk.Label(pred_frame, text="预测天数:").grid(
            row=0, column=0, padx=5, pady=2, sticky=tk.W)
        self.pred_days_entry = ttk.Entry(pred_frame, width=10)
        self.pred_days_entry.grid(row=0, column=1, padx=5, pady=2)
        self.pred_days_entry.insert(0, "365")

        ttk.Button(pred_frame, text="开始预测", command=self.run_prediction).grid(
            row=0, column=2, padx=5, pady=2)

        # 预测结果
        result_frame = ttk.LabelFrame(parent, text="预测结果", padding="10")
        result_frame.pack(fill=tk.BOTH, expand=True, pady=5)

        self.info_labels = {}
        result_data = [
            ("轨道类型", "待计算"),
            ("轨道计算最亮星等", "待计算"),
            ("轨道计算最亮日期", "待计算"),
            ("观测拟合最亮星等", "待计算"),
            ("观测拟合最亮日期", "待计算"),
            ("近日点日期", "待计算"),
            ("亮度差异", "待计算"),
            ("预测总天数", "待计算")
        ]

        for i, (label, value) in enumerate(result_data):
            ttk.Label(result_frame, text=label + ":").grid(row=i,
                                                           column=0, padx=5, pady=2, sticky=tk.W)
            value_label = ttk.Label(result_frame, text=value)
            value_label.grid(row=i, column=1, padx=5, pady=2, sticky=tk.W)
            self.info_labels[label] = value_label

    def setup_query_tab(self, parent):
        """设置日期查询标签页"""
        # 日期查询
        query_frame = ttk.LabelFrame(parent, text="日期查询", padding="10")
        query_frame.pack(fill=tk.X, pady=5)

        ttk.Label(query_frame, text="查询日期:").grid(
            row=0, column=0, padx=5, pady=2, sticky=tk.W)
        self.query_date_entry = ttk.Entry(query_frame, width=15)
        self.query_date_entry.grid(row=0, column=1, padx=5, pady=2)
        self.query_date_entry.insert(0, datetime.now().strftime('%Y-%m-%d'))

        ttk.Button(query_frame, text="查询亮度", command=self.query_brightness).grid(
            row=0, column=2, padx=5, pady=2)

        # 查询结果
        result_frame = ttk.LabelFrame(parent, text="查询结果", padding="10")
        result_frame.pack(fill=tk.BOTH, expand=True, pady=5)

        self.query_result = tk.StringVar()
        self.query_result.set("请输入日期并点击查询")
        ttk.Label(result_frame, textvariable=self.query_result, wraplength=400).pack(
            fill=tk.BOTH, expand=True, padx=5, pady=5)

    def on_comet_selected(self, event):
        """彗星选择事件处理"""
        comet_name = self.comet_var.get()
        self.fill_comet_data(comet_name)

    def fill_sample_data(self):
        """填充示例数据"""
        self.comet_var.set("C/2025 A6 (Lemmon)")
        self.fill_comet_data("C/2025 A6 (Lemmon)")

    def fill_comet_data(self, comet_name):
        """根据选择的彗星填充数据"""
        comet_data = {
            "C/2025 A6 (Lemmon)": {
                "name": "C/2025 A6 (Lemmon)",
                "orbit": {
                    "perihelion_distance": "0.529889",
                    "semi_major_axis": "121.283818",
                    "eccentricity": "0.995631",
                    "arg_perihelion": "132.9699",
                    "long_asc_node": "108.0978",
                    "inclination": "143.6635",
                    "orbital_period": "1335.7395",
                    "perihelion_time": "2025-11-08 12:53:59",
                    "epoch_time": "2025-10-04"
                },
                "orbit_H": "13.2",
                "orbit_n": "10",
                "obs_H": "6.9",
                "obs_n": "3.9"
            },
            "C/2025 R2 (SWAN)": {
                "name": "C/2025 R2 (SWAN)",
                "orbit": {
                    "perihelion_distance": "0.504053",
                    "semi_major_axis": "76.522393",
                    "eccentricity": "0.993413",
                    "arg_perihelion": "308.3194",
                    "long_asc_node": "335.3460",
                    "inclination": "4.4736",
                    "orbital_period": "669.4225",
                    "perihelion_time": "2025-09-12 19:55:55",
                    "epoch_time": "2025-10-04"
                },
                "orbit_H": "12.4",
                "orbit_n": "10",
                "obs_H": "8.8",
                "obs_n": "2.0"
            },
            "C/2025 K1 (ATLAS)": {
                "name": "C/2025 K1 (ATLAS)",
                "orbit": {
                    "perihelion_distance": "0.334197",
                    "semi_major_axis": "-1270.711026",
                    "eccentricity": "1.000263",
                    "arg_perihelion": "271.0256",
                    "long_asc_node": "97.5572",
                    "inclination": "147.8645",
                    "orbital_period": "",
                    "perihelion_time": "2025-10-08 10:31:34",
                    "epoch_time": "2025-10-04"
                },
                "orbit_H": "12.2",
                "orbit_n": "10",
                "obs_H": "12.4",
                "obs_n": "3.0"
            },
            "210P/Christensen": {
                "name": "210P/Christensen",
                "orbit": {
                    "perihelion_distance": "0.524416",
                    "semi_major_axis": "3.160446",
                    "eccentricity": "0.834069",
                    "arg_perihelion": "345.9494",
                    "long_asc_node": "93.7975",
                    "inclination": "10.2873",
                    "orbital_period": "5.6188",
                    "perihelion_time": "2025-11-22 17:25:43",
                    "epoch_time": "2025-10-04"
                },
                "orbit_H": "13.5",
                "orbit_n": "10",
                "obs_H": "13.5",
                "obs_n": "4.0"
            },
            "3I/ATLAS": {
                "name": "3I/ATLAS",
                "orbit": {
                    "perihelion_distance": "1.356324",
                    "semi_major_axis": "-0.263949",
                    "eccentricity": "6.138574",
                    "arg_perihelion": "128.0125",
                    "long_asc_node": "322.1574",
                    "inclination": "175.1131",
                    "orbital_period": "",
                    "perihelion_time": "2025-10-29 11:35:39",
                    "epoch_time": "2025-11-21"
                },
                "orbit_H": "11.8",
                "orbit_n": "10",
                "obs_H": "6.8",
                "obs_n": "6.0"
            },
            "C/2024 E1 (Wierzchos)": {
                "name": "C/2024 E1 (Wierzchos)",
                "orbit": {
                    "perihelion_distance": "0.566072",
                    "semi_major_axis": "-7351.584415",
                    "eccentricity": "1.000077",
                    "arg_perihelion": "243.6283",
                    "long_asc_node": "108.0793",
                    "inclination": "75.2398",
                    "orbital_period": "",
                    "perihelion_time": "2026-01-20 18:23:28",
                    "epoch_time": "2025-10-04"
                },
                "orbit_H": "7.0",
                "orbit_n": "10",
                "obs_H": "7.6",
                "obs_n": "5.0"
            }
        }

        if comet_name in comet_data:
            data = comet_data[comet_name]

            # 清空现有数据
            self.clear_entries()

            # 填充新数据
            self.name_entry.insert(0, data["name"])

            for key, value in data["orbit"].items():
                if value:
                    self.orbit_entries[key].insert(0, value)

            self.orbit_H_entry.insert(0, data["orbit_H"])
            self.orbit_n_entry.insert(0, data["orbit_n"])
            self.obs_H_entry.insert(0, data["obs_H"])
            self.obs_n_entry.insert(0, data["obs_n"])

    def clear_entries(self):
        """清空所有输入框"""
        self.name_entry.delete(0, tk.END)
        for entry in self.orbit_entries.values():
            entry.delete(0, tk.END)
        self.orbit_H_entry.delete(0, tk.END)
        self.orbit_n_entry.delete(0, tk.END)
        self.obs_H_entry.delete(0, tk.END)
        self.obs_n_entry.delete(0, tk.END)
        self.query_date_entry.delete(0, tk.END)
        self.query_result.set("已重置所有参数")

    def validate_inputs(self):
        """验证输入数据"""
        try:
            # 获取基本输入
            comet_name = self.name_entry.get().strip()
            if not comet_name:
                raise ValueError("请输入彗星名称")

            # 获取轨道参数
            q = float(self.orbit_entries["perihelion_distance"].get())
            a_str = self.orbit_entries["semi_major_axis"].get()
            a = float(a_str) if a_str else abs(
                q / (1 - float(self.orbit_entries["eccentricity"].get())))
            e = float(self.orbit_entries["eccentricity"].get())
            peri_time_str = self.orbit_entries["perihelion_time"].get()

            # 获取轨道计算参数
            orbit_H = float(self.orbit_H_entry.get())
            orbit_n = float(self.orbit_n_entry.get())

            # 获取观测拟合参数
            obs_H = float(self.obs_H_entry.get())
            obs_n = float(self.obs_n_entry.get())

            # 验证参数范围
            if not 0.0001 <= q <= 1000:
                raise ValueError("近日点距离应在0.0001-1000AU范围内")
            if e < 0:
                raise ValueError("偏心率不能为负")
            if not -20 <= orbit_H <= 100 or not -20 <= obs_H <= 100:
                raise ValueError("绝对星等应在-20-100范围内")
            if not -50 <= orbit_n <= 1000 or not -50 <= obs_n <= 1000:
                raise ValueError("斜率参数应在-50-1000范围内")

            # 解析近日点时间
            peri_date = datetime.strptime(peri_time_str, "%Y-%m-%d %H:%M:%S")

            return comet_name, q, a, e, peri_date, orbit_H, orbit_n, obs_H, obs_n

        except Exception as e:
            messagebox.showerror("输入错误", str(e))
            return None

    def query_brightness(self):
        """查询指定日期的亮度"""
        inputs = self.validate_inputs()
        if inputs is None:
            return

        comet_name, q, a, e, peri_date, orbit_H, orbit_n, obs_H, obs_n = inputs

        try:
            # 获取查询日期
            query_date_str = self.query_date_entry.get()
            query_date = datetime.strptime(query_date_str, "%Y-%m-%d")

            # 计算轨道距离
            days_from_peri = (query_date - peri_date).days
            if e < 1:
                # 椭圆轨道
                M = 2 * np.pi * days_from_peri / (a**1.5 * 365.25)
                E = self.solve_kepler_equation(M, e)
                r = a * (1 - e * np.cos(E))
            else:
                # 双曲线轨道
                N = 2 * np.pi * days_from_peri / ((-a)**1.5 * 365.25)
                H = self.solve_hyperbolic_kepler_equation(N, e)
                r = a * (1 - e * np.cosh(H))

            # 计算地彗距
            delta = np.sqrt(r**2 + 1 - 2*r*np.cos(np.radians(45)))

            # 计算两种预测方法的星等
            orbit_m = orbit_H + 5 * \
                np.log10(delta) + 2.5 * orbit_n * np.log10(r)
            obs_m = obs_H + 5 * np.log10(delta) + 2.5 * obs_n * np.log10(r)

            # 显示结果
            result_text = (
                f"彗星: {comet_name}\n"
                f"查询日期: {query_date_str}\n"
                f"日彗距: {r:.6f} AU\n"
                f"地彗距: {delta:.6f} AU\n"
                f"轨道计算预测: {orbit_m:.2f} 等\n"
                f"观测拟合预测: {obs_m:.2f} 等\n"
                f"亮度差异: {abs(orbit_m - obs_m):.2f} 等"
            )
            self.query_result.set(result_text)

        except Exception as e:
            messagebox.showerror("查询错误", str(e))

    def run_prediction(self):
        """运行亮度预测"""
        inputs = self.validate_inputs()
        if inputs is None:
            return

        comet_name, q, a, e, peri_date, orbit_H, orbit_n, obs_H, obs_n = inputs

        try:
            future_days = int(self.pred_days_entry.get())
            if not 1 <= future_days <= 3650000:
                raise ValueError("预测天数应在1-3650000范围内")

            # 生成时间序列
            start_date = peri_date - timedelta(days=future_days//2)
            all_dates = [start_date + timedelta(days=i)
                         for i in range(future_days)]

            # 计算轨道距离
            r_pred = []
            for date in all_dates:
                days_from_peri = (date - peri_date).days
                if e < 1:
                    # 椭圆轨道
                    M = 2 * np.pi * days_from_peri / (a**1.5 * 365.25)
                    E = self.solve_kepler_equation(M, e)
                    r = a * (1 - e * np.cos(E))
                else:
                    # 双曲线轨道
                    N = 2 * np.pi * days_from_peri / ((-a)**1.5 * 365.25)
                    H = self.solve_hyperbolic_kepler_equation(N, e)
                    r = a * (1 - e * np.cosh(H))
                r_pred.append(r)

            r_pred = np.array(r_pred)

            # 计算地彗距
            delta_pred = np.sqrt(
                r_pred**2 + 1 - 2*r_pred*np.cos(np.radians(45)))

            # 计算星等
            orbit_m_pred = orbit_H + 5 * \
                np.log10(delta_pred) + 2.5 * orbit_n * np.log10(r_pred)
            obs_m_pred = obs_H + 5 * \
                np.log10(delta_pred) + 2.5 * obs_n * np.log10(r_pred)

            # 应用物理约束
            orbit_m_pred = np.clip(orbit_m_pred, -100, 30000)
            obs_m_pred = np.clip(obs_m_pred, -100, 30000)

            # 存储当前数据用于鼠标悬停
            self.current_dates = all_dates
            self.orbit_m_pred = orbit_m_pred
            self.obs_m_pred = obs_m_pred

            # 绘制图表
            self.plot_results(comet_name, e, all_dates, r_pred,
                              delta_pred, orbit_m_pred, obs_m_pred)

            # 更新结果信息
            self.update_results(comet_name, e, orbit_m_pred,
                                obs_m_pred, all_dates, r_pred, future_days)

        except Exception as e:
            messagebox.showerror("预测错误", str(e))

    def solve_kepler_equation(self, M, e, tol=1e-6, max_iter=50):
        """解开普勒方程（椭圆轨道）"""
        E = M
        for _ in range(max_iter):
            delta = (E - e * np.sin(E) - M) / (1 - e * np.cos(E))
            E -= delta
            if abs(delta) < tol:
                break
        return E

    def solve_hyperbolic_kepler_equation(self, N, e, tol=1e-6, max_iter=50):
        """解双曲线开普勒方程"""
        H = N
        for _ in range(max_iter):
            delta = (e * np.sinh(H) - H - N) / (e * np.cosh(H) - 1)
            H -= delta
            if abs(delta) < tol:
                break
        return H

    def plot_results(self, comet_name, e, all_dates, r_pred, delta_pred, orbit_m_pred, obs_m_pred):
        """绘制预测结果"""
        self.ax1.clear()
        self.ax2.clear()

        # 确定轨道类型
        if e < 1:
            orbit_type = "椭圆轨道"
        elif e == 1:
            orbit_type = "抛物线轨道"
        else:
            orbit_type = "双曲线轨道"

        # 绘制亮度曲线
        self.ax1.plot(all_dates, orbit_m_pred, 'orange',
                      label='轨道计算 (MPC)', linewidth=2)
        self.ax1.plot(all_dates, obs_m_pred, 'darkgreen',
                      label='观测拟合 (COBS)', linewidth=2)

        # 标记最亮点
        orbit_min_mag = min(orbit_m_pred)
        orbit_min_idx = np.argmin(orbit_m_pred)
        self.ax1.plot(all_dates[orbit_min_idx], orbit_min_mag, 'o',
                      color='orange', markersize=8, label=f'轨道计算最亮: {orbit_min_mag:.2f}等')

        obs_min_mag = min(obs_m_pred)
        obs_min_idx = np.argmin(obs_m_pred)
        self.ax1.plot(all_dates[obs_min_idx], obs_min_mag, 'o',
                      color='darkgreen', markersize=8, label=f'观测拟合最亮: {obs_min_mag:.2f}等')

        # 标记近日点
        peri_idx = np.argmin(r_pred)
        peri_mag_orbit = orbit_m_pred[peri_idx]
        peri_mag_obs = obs_m_pred[peri_idx]
        self.ax1.plot(all_dates[peri_idx], peri_mag_orbit, 'D', color='red',
                      markersize=6, label=f'近日点轨道计算: {peri_mag_orbit:.2f}等')
        self.ax1.plot(all_dates[peri_idx], peri_mag_obs, 'D', color='blue',
                      markersize=6, label=f'近日点观测拟合: {peri_mag_obs:.2f}等')

        self.ax1.set_ylabel("视星等")
        self.ax1.set_title(f"{comet_name}亮度预测 - {orbit_type}", fontsize=12)
        self.ax1.grid(True, alpha=0.3)
        self.ax1.legend()
        self.ax1.invert_yaxis()

        # 绘制距离曲线
        self.ax2.plot(all_dates, r_pred, 'orange', label='日彗距', linewidth=2)
        self.ax2.plot(all_dates, delta_pred, 'darkgreen',
                      label='地彗距', linewidth=2)

        # 标记近日点
        peri_dist = r_pred[peri_idx]
        self.ax2.plot(all_dates[peri_idx], peri_dist, 'D', color='red',
                      markersize=6, label=f'近日点: {peri_dist:.6f} AU')

        self.ax2.set_ylabel("距离 (AU)")
        self.ax2.set_xlabel("日期")
        self.ax2.grid(True, alpha=0.3)
        self.ax2.legend()

        self.fig.tight_layout()
        self.canvas.draw()

    def update_results(self, comet_name, e, orbit_m_pred, obs_m_pred, all_dates, r_pred, future_days):
        """更新预测结果信息"""
        # 确定轨道类型
        if e < 1:
            orbit_type = f"椭圆轨道 (e={e:.6f})"
        elif e == 1:
            orbit_type = "抛物线轨道 (e=1.000000)"
        else:
            orbit_type = f"双曲线轨道 (e={e:.6f})"

        # 轨道计算结果
        orbit_min_mag = min(orbit_m_pred)
        orbit_min_idx = np.argmin(orbit_m_pred)
        orbit_min_date = all_dates[orbit_min_idx].strftime('%Y-%m-%d')

        # 观测拟合结果
        obs_min_mag = min(obs_m_pred)
        obs_min_idx = np.argmin(obs_m_pred)
        obs_min_date = all_dates[obs_min_idx].strftime('%Y-%m-%d')

        # 亮度差异
        mag_diff = abs(orbit_min_mag - obs_min_mag)

        # 查找近日点
        peri_idx = np.argmin(r_pred)
        peri_date = all_dates[peri_idx].strftime('%Y-%m-%d')

        # 计算预测总天数
        total_days = (all_dates[-1] - all_dates[0]).days

        # 更新界面显示
        self.info_labels["轨道类型"].config(text=orbit_type)
        self.info_labels["轨道计算最亮星等"].config(text=f"{orbit_min_mag:.2f}")
        self.info_labels["轨道计算最亮日期"].config(text=orbit_min_date)
        self.info_labels["观测拟合最亮星等"].config(text=f"{obs_min_mag:.2f}")
        self.info_labels["观测拟合最亮日期"].config(text=obs_min_date)
        self.info_labels["近日点日期"].config(text=peri_date)
        self.info_labels["亮度差异"].config(text=f"{mag_diff:.2f} 等")
        self.info_labels["预测总天数"].config(text=f"{total_days:,} 天")


# 主程序
if __name__ == "__main__":
    root = tk.Tk()
    app = CometBrightnessApp(root)
    root.mainloop()
